<template>
    <div class="ai-wrap">
        <div class="ai" @click="openDrawer">企业合规大模型助手</div>
        <el-drawer v-model="drawer" :with-header="false" size="1300">
            <div class="ai-drawer">
                <div class="ai-left">
                    <div class="title">企业合规大模型助手</div>
                    <el-button class="add" @click="addSession"><span
                            class="iconfont icon-tianjia"></span>新对话</el-button>
                    <div class="history">
                        <div class="tit">历史对话</div>
                        <el-scrollbar class="scrollbar">
                            <div v-for="(item, index) in historyList" :key="index" class="item"
                                :class="{ active: item.id == currentSessionId }" @click="selectSession(item)">
                                <div class="edit" v-if="item.isEdit">
                                    <el-input v-model="item.title"></el-input>
                                    <el-icon :size="20" color="#afb0b2" style="margin-left: 5px; cursor: pointer;"
                                        @click="editSessionTitle(item)">
                                        <Check />
                                    </el-icon>
                                    <el-icon :size="20" color="#afb0b2" style="margin-left: 5px; cursor: pointer;"
                                        @click="item.isEdit = false">
                                        <Close />
                                    </el-icon>
                                </div>
                                <div class="question-title" v-else>
                                    <p :title="item.title">{{ item.title }}</p>
                                    <el-icon :size="16" color="#afb0b2" style="margin-left: 5px; cursor: pointer;"
                                        @click="item.isEdit = true">
                                        <EditPen />
                                    </el-icon>
                                    <el-icon :size="16" color="#afb0b2" style="margin-left: 5px; cursor: pointer;"
                                        @click.stop="deleteSession(item)">
                                        <Delete />
                                    </el-icon>
                                </div>
                            </div>
                        </el-scrollbar>
                    </div>
                </div>
                <div class="ai-right">

                    <div class="chat">
                        <div class="questions" v-if="messages.length === 0">
                            <p class="welcome">您好，我是您的24小时人力合规助手。<br />
                                我可以帮您回答招聘、入职、绩效和员工关系中的合规问题。需要时，我随时为您服务。<br />
                                有什么问题需要解决吗？</p>
                            <div class="title">
                                <span>你还可以尝试问我</span>
                                <el-button text :icon="RefreshRight" class="change"
                                    @click="getQuestionList">换一批</el-button>
                            </div>
                            <div class="question">
                                <div class="item" v-for="(item, index) in questionList" :key="index"
                                    @click="selectQuestion(item)">
                                    <div class="item-title">#{{ item.parent.Question }}</div>
                                    <div class="item-content">{{ item.Question }}</div>
                                </div>
                            </div>
                        </div>
                        <el-scrollbar class="scrollbar" ref="scrollbarRef" v-else>
                            <div class="custom"></div>
                            <div class="msg-wrap" v-for="(item, index) in messages" :key="index">
                                <div class="msg ask">
                                    <el-avatar :src="userStore.userInfo.avatar" :size="50" style="flex-shrink: 0;" />
                                    <div>
                                        <div class="content">{{ item.question }}</div>
                                        <el-tag style="margin: 5px 0 0 10px;" v-if="item.file_name">{{ item.file_name
                                            }}</el-tag>
                                    </div>
                                </div>
                                <div class="msg answer">
                                    <el-avatar :src="aiAvatar" :size="50"
                                        style="border: solid 1px #eee; flex-shrink: 0;" />
                                    <div class="content">
                                        <template v-if="item.content">
                                            <template v-for="(line, index) in splitText(item.content)" :key="index">
                                                {{ line }}<br v-if="index < splitText(item.content).length - 1">
                                            </template>
                                            <span class="typing-cursor"
                                                v-if="isLoading && messages.length - 1 === index">|</span>
                                            <div class="toolbar" v-if="!isLoading">
                                                <div class="menu" @click="copyContent(item.content)">
                                                    <el-icon :size="18" color="#333">
                                                        <CopyDocument />
                                                    </el-icon>
                                                    <span>复制</span>
                                                </div>
                                                <div class="menu" @click="reGenerate(item)">
                                                    <el-icon :size="18" color="#333">
                                                        <RefreshRight />
                                                    </el-icon>
                                                    <span>重新生成</span>
                                                </div>
                                            </div>
                                        </template>
                                        <div class="loaders" v-else>
                                            <span class="col"></span>
                                            <span class="col"></span>
                                            <span class="col"></span>
                                            <span class="col"></span>
                                            <span class="col"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>

                        </el-scrollbar>
                        <div class="input-box">
                            <el-input v-model="userInput" type="textarea" resize="none" class="input" :style="{
                                '--el-border-color': 'rgba(255,255,255,0.0)',
                                '--el-input-focus-border-color': 'rgba(255,255,255,0.0)',
                                '--el-input-focus-border-width': '0px',
                                '--el-input-hover-border-color': 'rgba(255,255,255,0.0)',
                                '--el-input-hover-border-width': '0px',
                                '--el-input-bg-color': 'rgba(255,255,255,0.0)'
                            }" @keyup.enter="sendMessageByEnter" placeholder="请您输入想问的问题，我将立即为您解答" />
                            <div class="input-bar">
                                <div class="file">
                                    <el-tag closable v-for="(item, index) in uploadFileList" :key="index"
                                        @close="clearAllFiles">{{ item }}</el-tag>
                                </div>
                                <el-upload ref="upload" class="upload" :action="uploadUrl" :limit="1"
                                    :show-file-list="false" :before-upload="beforeUpload" :auto-upload="true"
                                    :on-success="handleSuccess" :disabled="uploadFileList.length > 0 || uploadLoading">
                                    <template #trigger>
                                        <el-tooltip content="上传文件" placement="top">
                                            <el-icon :size="24" :color="uploadLoading ? '#ccc' : '#afb0b2'"
                                                style="margin-right: 10px;">
                                                <Document />
                                            </el-icon>
                                        </el-tooltip>
                                        <el-tooltip content="上传图片" placement="top">
                                            <el-icon :size="24" :color="uploadLoading ? '#ccc' : '#afb0b2'"
                                                style="margin-right: 10px;">
                                                <Picture />
                                            </el-icon>
                                        </el-tooltip>
                                    </template>
                                    <template #tip>
                                        <div class="upload-loading" v-if="uploadLoading">
                                            <el-icon class="is-loading">
                                                <Loading />
                                            </el-icon>
                                            上传中...
                                        </div>
                                    </template>
                                </el-upload>

                                <el-button type="primary" @click="sendMessage" :disabled="uploadLoading">{{
                                    isLoading ? '停止' : '发送' }}</el-button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </el-drawer>
    </div>
</template>
<script lang="ts" setup>
import { baseURL } from '@/api'
import { ChangeSession, DelSession, QuestionList, SaveLog, SessionInfo, SessionList } from '@/api/ai'
import aiAvatar from '@/assets/enterprise/ai-avatar.png'
import { useUserStore } from '@/store/user'
import { RefreshRight } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
import { ElMessage } from 'element-plus'
import { nextTick, ref, watch } from 'vue'

interface Msg {
    question: string;
    content: string;
    session_id: string;
    fileId: string;
    file_name: string;
    file_url: string;
}

interface Session {
    id: number;
    title: string;
    isEdit: boolean;
    create_time: string;
    user_id: number;
    is_del: number;
    session_id: string;
}

interface Question {
    parent: QuestionParent;
    Question: string;
}

interface QuestionParent {
    Question: string;
}

const userStore = useUserStore()

const drawer = ref(false)
const show = ref(true)
const historyList = ref<Session[]>([])
const currentSessionId = ref(0)
const userInput = ref('')
const scrollbarRef = ref(null)
const messages = ref<Msg[]>([])
const isLoading = ref(false)
const sseInstance = ref(null)
const questionList = ref<Question[]>([])
const upload = ref()
const uploadUrl = `${baseURL}/hr/bailian/upload_file`
const uploadFileList = ref<string[]>([])
const fileId = ref('')
const fileUrl = ref('')
const uploadLoading = ref(false)


const openDrawer = () => {
    drawer.value = true
    currentSessionId.value = 0
    messages.value = []
    getSessionList()
    getQuestionList()
    setTimeout(() => {
        scrollToBottom()
    }, 100)
}

const addSession = () => {
    if (isLoading.value) {
        stopGenerating()
    }
    messages.value = []
    currentSessionId.value = 0
    userInput.value = ''
}

const copyContent = async (text: string) => {
    try {
        await navigator.clipboard.writeText(text);
        ElMessage({
            message: '已复制到剪贴板',
            type: 'success',
            duration: 2000
        });
    } catch (err) {
        ElMessage.error('复制失败，请手动选择文本');
    }
}

const reGenerate = (item: Msg) => {
    userInput.value = item.question
    fileId.value = item.fileId
    fileUrl.value = item.file_url
    uploadFileList.value = [item.file_name]
    sendMessage()
}

const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
    uploadLoading.value = true
    // if (rawFile.type !== 'image/jpeg') {
    //     ElMessage.error('Avatar picture must be JPG format!')
    //     return false
    // } 
    if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('文件或照片大小不能大于2MB')
        uploadLoading.value = false
        return false
    }
    return true
}

const handleSuccess: UploadProps['onSuccess'] = (
    response,
    uploadFile
) => {
    fileId.value = response.data.fileId
    fileUrl.value = response.data.url
    uploadFileList.value.push(uploadFile.name)
    uploadLoading.value = false
}

const clearAllFiles = () => {
    upload.value?.clearFiles()
    uploadFileList.value = []
    fileId.value = ''
    fileUrl.value = ''
}

const getSessionList = async () => {
    await SessionList('').then(res => {
        let list = res.data
        list.forEach((item: Session) => {
            item.isEdit = false
        })
        historyList.value = list
    })
}

const getQuestionList = () => {
    QuestionList().then(res => {
        questionList.value = res.data
    })
}

const selectSession = (item: Session) => {
    currentSessionId.value = item.id
    SessionInfo({
        session_id: item.session_id
    }).then(res => {
        messages.value = res.data
    })
}

const editSessionTitle = (item: Session) => {
    ChangeSession({
        title: item.title,
        session_id: item.session_id
    }).then(() => {
        item.isEdit = false
    })
}

const deleteSession = (item: Session) => {
    DelSession({
        session_id: item.session_id
    }).then(() => {
        ElMessage.success('删除成功')
        if (item.id == currentSessionId.value) {
            messages.value = []
        }
        getSessionList()
    })
}

const selectQuestion = (item: Question) => {
    userInput.value = item.Question
    sendMessage()
}

const sendMessageByEnter = () => {
    if (isLoading.value) {
        return ElMessage({
            message: 'AI正在回答，请稍候...',
            type: 'warning',
            plain: true,
        })
    }
    sendMessage()
}

const sendMessage = async () => {
    if (!isLoading.value && userInput.value == '') return
    stopGenerating()
    if (!userInput.value.trim()) return
    const session_id = messages.value.length > 0 ? messages.value[messages.value.length - 1].session_id : ''
    // 添加用户消息
    messages.value.push({
        question: userInput.value,
        content: '',
        session_id: session_id,
        fileId: fileId.value,
        file_name: uploadFileList.value.length > 0 ? uploadFileList.value[0] : '',
        file_url: fileUrl.value
    })

    // 清空输入框
    const question = userInput.value
    userInput.value = ''
    const file_id = fileId.value
    const file_name = uploadFileList.value.length > 0 ? uploadFileList.value[0] : ''
    const file_url = fileUrl.value

    clearAllFiles()

    // 连接SSE
    await connectSSE(question, session_id, file_id, file_name, file_url)
}

const connectSSE = async (question: string, session_id: string, fileId: string = '', file_name: string = '', file_url: string = '') => {
    // 关闭现有连接
    if (sseInstance.value) {
        sseInstance.value.close()
        sseInstance.value = null
    }

    const params = {
        content: question,
        session_id: session_id,
        fileId: fileId,
        file_name: file_name,
        file_url: file_url
    }

    try {
        isLoading.value = true

        // 使用fetch发起POST请求
        const response = await fetch(`${baseURL}/hr/bailian/completion`,
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-DashScope-SSE': 'enable',
                    'token': localStorage.getItem("token") || ''
                },
                body: JSON.stringify(params)
            }
        )

        // 验证响应
        if (!response.ok || !response.body) {
            throw new Error(`HTTP error! status: ${response.status}`)
        }

        // 处理流式响应
        const reader = response.body.getReader()
        const decoder = new TextDecoder()
        let partialData = ''

        const processStream = async () => {
            while (true) {
                const { done, value } = await reader.read()
                if (done) {
                    isLoading.value = false
                    if (messages.value.length == 1) {
                        await getSessionList()
                        currentSessionId.value = historyList.value[0].id
                    }
                    break
                }



                const chunk = decoder.decode(value, { stream: true })
                partialData += chunk

                // 处理阿里云SSE格式（data: {...}\n\n）
                const lines = partialData.split('\n')
                partialData = lines.pop() // 保留未完成的行
                for (const line of lines) {
                    if (line.startsWith('data:')) {
                        try {
                            const data = JSON.parse(line.substring(5).trim())
                            if (data.output?.text) {
                                messages.value[messages.value.length - 1].session_id = data.output.session_id
                                messages.value[messages.value.length - 1].content += data.output.text
                                scrollToBottom()
                            }
                        } catch (e) {
                            console.error('解析SSE数据失败:', e)
                        }
                    }
                }
            }
        }

        sseInstance.value = { close: () => reader.cancel() }
        processStream()

    } catch (error: any) {
        isLoading.value = false
        messages.value[messages.value.length - 1].content = `请求失败: ${error.message}`
    }
}

const stopGenerating = () => {
    if (sseInstance.value && isLoading.value) {
        SaveLog({
            session_id: messages.value[messages.value.length - 1].session_id,
            content: messages.value[messages.value.length - 1].content ? messages.value[messages.value.length - 1].content + '用户停止回答' : '用户停止回答',
            file_url: messages.value[messages.value.length - 1].file_url,
            question: messages.value[messages.value.length - 1].question,
            file_name: messages.value[messages.value.length - 1].file_name
        }).then(() => {
            if (messages.value.length == 1) {
                messages.value[messages.value.length - 1].content = messages.value[messages.value.length - 1].content ? messages.value[messages.value.length - 1].content + '用户停止回答' : '用户停止回答'
                getSessionList()
                currentSessionId.value = historyList.value[0].id
            }
        })
        sseInstance.value.close()
        sseInstance.value = null
        isLoading.value = false
        // ElMessage.info('响应已停止')
    }
}

const splitText = (text: string) => {
    return text.split('\n').filter(line => line.trim() !== '')
}

watch(messages, () => {
    nextTick(() => {
        scrollToBottom()
    })
}, { deep: true })

watch(isLoading, () => {
    nextTick(() => {
        setTimeout(() => {
            scrollToBottom()
        }, 200)
    })
}, { deep: true })

function scrollToBottom() {
    const scrollbarContainer = scrollbarRef.value?.$el.querySelector('.el-scrollbar__wrap')
    if (scrollbarContainer) {
        scrollbarContainer.scrollTop = scrollbarContainer.scrollHeight
    }
}
</script>
<style lang="scss" scoped>
.ai-wrap {
    .ai {
        font-size: 16px;
        width: 173px;
        height: 40px;
        text-align: center;
        line-height: 40px;
        background-image: linear-gradient(to right, #0259a9, #6aa5dd);
        margin-right: 30px;
        color: #fff;
        border-radius: 5px;
        cursor: pointer;
    }

    .ai-drawer {
        display: flex;

        .ai-left {
            width: 350px;
            height: 100vh;
            background-color: #f4f7ff;

            .title {
                height: 75px;
                line-height: 75px;
                font-size: 23px;
                color: #01509f;
                text-align: center;
                font-weight: bold;
            }

            .add {
                width: 310px;
                height: 45px;
                border: solid 1px #6092cb;
                background-color: #e3ecff;
                color: #1f65ac;
                margin: 0 auto;
                display: block;
                font-size: 16px;
                display: flex;
                align-items: center;

                span{
                    margin-right: 5px;
                    margin-top: -2px;
                }
            }

            .history {
                padding: 15px 13px;
                border-top: solid 1px #eee;
                margin-top: 20px;

                .tit {
                    font-size: 14px;
                    color: #666;
                }

                .scrollbar {
                    height: calc(100vh - 180px);

                    .item {
                        height: 46px;
                        padding: 0 8px;
                        border-radius: 5px;
                        margin-top: 4px;
                        cursor: pointer;

                        &.active {
                            background-color: #eaf1ff;
                        }

                        .question-title {
                            display: flex;
                            align-items: center;
                            height: inherit;
                        }

                        p {
                            font-size: 16px;
                            flex: 1;
                            white-space: nowrap;
                            overflow: hidden;
                            text-overflow: ellipsis;
                        }

                        &:hover {
                            background-color: #eaf1ff;
                        }

                        .edit {
                            display: flex;
                            align-items: center;
                            height: inherit;
                            font-size: 16px;
                        }
                    }
                }
            }
        }

        .ai-right {
            padding: 0 20px 20px 20px;
            flex: 1;

            .welcome {
                font-size: 18px;
                color: #333;
                line-height: 32px;
                padding-top: 20px;
            }

            .title {
                display: flex;
                align-items: center;
                justify-content: space-between;
                margin-top: 20px;

                span {
                    font-size: 16px;
                    color: #666;
                }

                .change {
                    font-size: 16px;
                    color: #01509f;
                }
            }

            .questions {
                height: calc(100vh - 172px);
            }

            .question {
                margin: 15px 0 0 0;
                display: flex;
                flex-wrap: wrap;
                justify-content: space-between;

                .item {
                    width: 250px;
                    border: solid 1px #eee;
                    padding: 20px;
                    margin-bottom: 10px;
                    cursor: pointer;

                    .item-title {
                        font-size: 16px;
                        color: #01509f;
                    }

                    .item-content {
                        font-size: 14px;
                        color: #666;
                        margin-top: 5px;
                        letter-spacing: 1px;
                    }
                }
            }

            .chat {
                display: flex;
                flex-direction: column;
                width: 100%;

                .scrollbar {
                    height: calc(100vh - 172px);
                    padding-right: 20px;

                    .custom {
                        height: 20px;
                    }

                    .msg-wrap {

                        .msg {
                            display: flex;
                            margin-bottom: 20px;

                            &.ask {
                                .content {
                                    background-color: #01509f;
                                    color: #fff;
                                }
                            }

                            &.answer {

                                .content {
                                    border: solid 1px #eee;

                                    .toolbar {
                                        display: flex;
                                        border-top: solid 1px #eee;
                                        margin-top: 10px;
                                        padding-top: 8px;

                                        .menu {
                                            display: flex;
                                            align-items: center;
                                            margin-right: 20px;
                                            cursor: pointer;

                                            span {
                                                font-size: 14px;
                                                color: #333;
                                                margin-left: 5px;
                                            }
                                        }
                                    }
                                }
                            }

                            .content {
                                font-size: 16px;
                                margin-left: 10px;
                                border-radius: 5px;
                                padding: 10px 12px;
                                line-height: 28px;

                                .typing-cursor {
                                    animation: blink .5s step-end infinite;
                                    color: #01509f;
                                    font-weight: bold;
                                }

                                @keyframes blink {

                                    from,
                                    to {
                                        opacity: 1;
                                    }

                                    50% {
                                        opacity: 0;
                                    }
                                }
                            }
                        }
                    }
                }

                .input-box {
                    display: flex;
                    flex-direction: column;
                    height: 120px;
                    padding: 15px;
                    border-radius: 10px;
                    border: solid 1px #eee;

                    .input {
                        width: 100%;

                        :deep(.el-textarea__inner) {
                            padding: 0;
                            border-radius: 0;
                            height: 95px;
                            font-size: 16px;
                        }
                    }

                    .input-bar {
                        height: 25px;
                        display: flex;
                        align-items: center;
                        justify-content: flex-end;

                        .file {
                            flex: 1;
                        }
                    }

                }
            }


        }
    }

    :deep(.el-drawer__body) {
        padding: 0;
    }
}

.upload {
    position: relative;
}

.upload-loading {
    position: absolute;
    top: 2px;
    left: -50px;
    color: #999;
    font-size: 14px;
}

.loaders {
    width: 40px;
    height: 40px;
    text-align: center;
    font-size: 12px;
}

.loaders>.col {
    background-color: #3366FF;
    height: 100%;
    width: 4px;
    margin: 0 2px;
    display: inline-block;
    animation: stretch 1.2s infinite ease-in-out;
}

.loaders>.col:nth-child(2) {
    animation-delay: -1.1s
}

.loaders>.col:nth-child(3) {
    animation-delay: -1s
}

.loaders>.col:nth-child(4) {
    animation-delay: -0.9s
}

.loaders>.col:nth-child(5) {
    animation-delay: -0.8s
}

@keyframes stretch {

    0%,
    40%,
    100% {
        transform: scaleY(0.45);
    }

    20% {
        transform: scaleY(1);
    }
}
</style>